#!/bin/python3
1. 什么是高阶函数和闭包并举例说明。
高阶函数：1、接受一个或多个函数A作为参数的函数B可以被称为高阶函数B。2、调用该函数A后返回值为函数B，这个函数A被称为高阶函数A
def highfunc(fn,*args,**kwargs):
    return func(*args,**kwargs)

def func(x,y):
    return x+y

print(highfunc(func,4,y=5))




def highfunc(n):
	def func(m):
		return m+n
	return func

foo1=highfunc(1)
print(foo1(2))
print(foo1(2))





def highfunc(fn):
    def func1(*args,**kwargs):
        ret=fn(*args,**kwargs)
        return ret
    return func1

def func(x,y):
    return x+y
print(highfunc(func)(2,3))



闭包：内层函数引用到了外层函数的自由变量，就形成了闭包
用到了闭包
def Closures(x):
	def inc(y=1):
		y+=x
		return y
	return inc

foo2=Closures(2)
print(foo2(2))
print(foo2(2))




用到了闭包
def Closures(fn):
	def clofunc(*args,**kwargs):
		ret=fn(*args,**kwargs)
		return ret
	return clofunc

def func(x,y):
	return x*y
print(Closures(func)(2,3))




没用到闭包，添加nonlocal使用外层函数x变量
def Closures(x):
    def func(y=1):
        nonlocal x
        x+=y
        return x
    return func
foo=Closures(0)
print(foo())
print(foo())

		
2. 请列出functools包内的每个函数的功能作用。
wraps：本质上调用的是update_wrapper，属性复制功能，用被包装函数的属性覆盖包装函数的同名属性，避免多个函数被两个装饰器装饰的时候就报错，因为两个函数同名，第二个函数再去装饰就会报错。
wraps(wrapped,assigned=WRAPPER_ASSIGNMENTS,update=WRAPPER_UPDATES)

reduce：减少可迭代对象里面的值交给接受两参函数function处理，把函数返回值当做函数下一次的参数，没有初始值就从可迭代对象中取一个
reduce(function,iterable[,initial])

partial：把函数部分参数固定下来，相当于为部分的参数添加了固定的默认值，形成一个新的函数，并返回这个新函数。

lru_cache：一个缓存装饰器，最近最少使用，内部使用一个字典，key是由_make_key函数造出来的。



3. 请使用已学习的装饰器相关知识自己实现functools.lru_cache。
#实现了简单缓存命中功能，没有控制
def lru_cache(maxsize=128):
	cache_dict={}
	def func(fn):
		def wrapper(*args,**kwargs):
			key=(args,tuple(kwargs.items()))
			if key in cache_dict:
				print('-'*30)
				return cache_dict[key]
			else:
				ret=fn(*args,**kwargs)
				cache_dict[key]=ret
				return ret
			if len(cache_dict)>maxsize:
				return None
				#这里需要多一项对cache_dict超出maxsize限制功能
		return wrapper
	return func

@lru_cache(maxsize=1) #lru_cache(maxsize=1)(add) ==> func(add)
def add(x,y):
	return x+y

print(add(2,3))
print(add(2,3))
print(add(2,y=3))
print(add(2,y=3))
print(add(x=2,y=3))
print(add(x=2,y=3))
print(add(2,3))
print(add(2,3))
print(add(2,y=3))


4. 什么是类型注解并说明其背后的目的。
类型注解在编程语言中用于指定变量、函数参数、函数返回值等的类型的方法。通过类型注解，开发者可以明确地告诉编译器变量的类型，从而提高代码的可读性和可靠性。在静态类型语言中，类型注解通常是必需的，因为编译器需要在编译时检查类型的正确性。而在动态类型语言中，类型注解通常是可选的，但可以提供编辑器和开发者更多的类型相关的提示和错误检查。

类型注解的目的是为了明确变量、函数、方法等的数据类型，以提高代码的可读性和可维护性，并帮助开发人员在编写代码时避免一些常见的类型错误。类型注解可以帮助开发人员更好地理解代码，减少潜在的bug，并提供更好地自动化工具支持，如代码补全，类型检查。
